﻿// Written by Dale J Williams.
// Licensed under MPL 1.1 unless otherwise specified. 
// http://www.mozilla.org/MPL/MPL-1.1.html

package engineDJW.display {
	
	import engineDJW.interfaces.ILoadable;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.geom.Matrix;
	import flash.net.URLRequest;
	
	/**
	 * ...
	 * @author Dale J Williams
	 */
	public class BitmapWidget extends Widget implements ILoadable {
		
		private var _url		:String;
		private var _bitmapData	:BitmapData;
		private var _cropping	:Boolean;
		private var _smoothing	:Boolean;
		private var _loadPC		:Number;
		private var _loaded		:Boolean;
		private var _matrix		:Matrix;
		
		public function BitmapWidget($url:String = null) {
			_url = $url;
			init();
		}
		
		private function init():void {
			smoothing = true;
			cropping = true;
			_loadPC = 0;
			_matrix = new Matrix();
			if (_url) load();
			onDraw = draw;
		}
		
		public function load($url:String=null):void {
			if ($url) _url = $url;
			_loadPC = 0;
			_loaded = false;
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
			loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
			loader.load(new URLRequest(_url));
		}
		
		private function loadProgress(e:ProgressEvent):void {
			_loadPC = e.bytesLoaded / e.bytesTotal;
		}
		
		private function loadComplete(e:Event):void {
			e.target.removeEventListener(Event.COMPLETE, loadComplete);
			e.target.removeEventListener(ProgressEvent.PROGRESS, loadProgress);
			e.target.removeEventListener(IOErrorEvent.IO_ERROR, loadError);
			if (_bitmapData) _bitmapData.dispose();
			_bitmapData = BitmapData(e.target.content.bitmapData);
			_loadPC = 1;
			_loaded = true;
			draw();
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		private function loadError(e:Event):void {
			e.target.removeEventListener(Event.COMPLETE, loadComplete);
			e.target.removeEventListener(ProgressEvent.PROGRESS, loadProgress);
			e.target.removeEventListener(IOErrorEvent.IO_ERROR, loadError);
			throw new Error("BitmapWidget error loading " + _url);
		}
		
		private function draw():void {
			if (!_bitmapData) return;
			if (_bitmapData.width < 1 || _bitmapData.height < 1) return;
			var byWidth:Boolean, rX:Number, rY:Number, oX:Number, oY:Number, pX:Number, pY:Number;
			
			rX = _width / _bitmapData.width;
			rY = _height / _bitmapData.height;		
			
			byWidth = rX < rY != _cropping;
			
			_matrix.a = byWidth ? rX : rY;
			_matrix.d = !byWidth ? rY : rX;
			
			oX = (_width - _bitmapData.width * _matrix.a) * 0.5;
			oY = (_height - _bitmapData.height * _matrix.d) * 0.5;
			
			_matrix.tx = !byWidth ? oX : 0;
			_matrix.ty = byWidth ? oY : 0;
			
			pX = _cropping ? 0 : oX; 
			pY = _cropping ? 0 : oY;
			
			graphics.clear();
			graphics.beginBitmapFill(_bitmapData, _matrix, true, _smoothing);
			graphics.drawRect(pX, pY, _width-pX*2, _height-pY*2);
			graphics.endFill();
		}
				
		public function get cropping():Boolean { return _cropping; }		
		public function set cropping(value:Boolean):void {
			_cropping = value;
			drawNextRender();
		}
		
		public function get smoothing():Boolean { return _smoothing; }		
		public function set smoothing(value:Boolean):void {
			_smoothing = value;
			drawNextRender();
		}
		
		public function get loadPercent():Number { return _loadPC; }
		
		public function get loadCompleted():Boolean { return _loaded; }
		
		public function get bitmapData():BitmapData { return _bitmapData; }		
		public function set bitmapData(value:BitmapData):void {
			_bitmapData = value;
			draw();
		}
		
		public function get url():String { return _url; }		
		public function set url(value:String):void {
			_url = value;
		}
		
	}

}